package com.springboot.study.tests.completablefuture;

import java.util.concurrent.CompletableFuture;

public class Test1 {

//    public static void main(String[] args) {
//
//        // 首先通过 supplyAsync() 启动一个异步流程，之后是两个串行操作，整体看起来还是挺简单的。
//        // 不过，虽然这是一个异步流程，但任务①②③却是串行执行的，②依赖①的执行结果，③依赖②的执行结果。
//        CompletableFuture<String> f0 =
//                CompletableFuture.supplyAsync(
//                        () -> "Hello World")      //①
//                        .thenApply(s -> s + " QQ")  //②
//                        .thenApply(String::toUpperCase);//③
//        System.out.println(f0.join());
//    }


//    public static void main(String[] args) throws Exception {
//
//        // 创建异步执行任务:
//        CompletableFuture<Double> cf = CompletableFuture.supplyAsync(Test1::fetchPrice);
//
//        // 如果执行成功:
//        cf.thenAccept((result) -> {
//            System.out.println("price: " + result);
//        });
//
//        // 如果执行异常:
//        cf.exceptionally((e) -> {
//            e.printStackTrace();
//            System.out.println("异常了啊 fuck");
//            return null;
//        });
//
//        // 主线程不要立刻结束，否则CompletableFuture默认使用的线程池会立刻关闭:
//        Thread.sleep(200);
//    }
//
//    static Double fetchPrice() {
//        try {
//            Thread.sleep(100);
//        } catch (InterruptedException e) {
//        }
//        if (Math.random() < 0.3) {
//            throw new RuntimeException("fetch price failed!");
//        }
//        return 5 + Math.random() * 20;
//    }




//    public static void main(String[] args) throws Exception {
//        // 第一个任务:
//        CompletableFuture<String> cfQuery = CompletableFuture.supplyAsync(() -> {
//            return queryCode("中国石油");
//        });
//
//        // cfQuery成功后继续执行下一个任务:
//        CompletableFuture<Double> cfFetch = cfQuery.thenApplyAsync((code1) -> {
//            return fetchPrice(code1);
//        });
//
//        // cfFetch成功后打印结果:
//        cfFetch.thenAccept((result) -> {
//            System.out.println("price: " + result);
//        });
//
//        // 主线程不要立刻结束，否则CompletableFuture默认使用的线程池会立刻关闭:
//        Thread.sleep(2000);
//    }
//
//    static String queryCode(String name) {
//        try {
//            Thread.sleep(100);
//        } catch (InterruptedException e) {
//        }
//        return "601857";
//    }
//
//    static Double fetchPrice(String code) {
//        try {
//            Thread.sleep(100);
//        } catch (InterruptedException e) {
//        }
//        return 5 + Math.random() * 20;
//    }



    public static void main(String[] args) throws Exception {

        // 两个CompletableFuture执行异步查询:
        CompletableFuture<String> cfQueryFromSina = CompletableFuture.supplyAsync(() -> {
            return queryCode("中国石油", "https://finance.sina.com.cn/code/");
        });

        CompletableFuture<String> cfQueryFrom163 = CompletableFuture.supplyAsync(() -> {
            return queryCode("中国石油", "https://money.163.com/code/");
        });

        // 用anyOf合并为一个新的CompletableFuture:
        CompletableFuture<Object> cfQuery = CompletableFuture.anyOf(cfQueryFromSina, cfQueryFrom163);

        // 两个CompletableFuture执行异步查询:
        CompletableFuture<Double> cfFetchFromSina = cfQuery.thenApplyAsync((code) -> {
            return fetchPrice((String) code, "https://finance.sina.com.cn/price/");
        });

        CompletableFuture<Double> cfFetchFrom163 = cfQuery.thenApplyAsync((code) -> {
            return fetchPrice((String) code, "https://money.163.com/price/");
        });

        // 用anyOf合并为一个新的CompletableFuture:
        CompletableFuture<Object> cfFetch = CompletableFuture.anyOf(cfFetchFromSina, cfFetchFrom163);

        // 最终结果:
        cfFetch.thenAccept((result) -> {
            System.out.println("price: " + result);
        });

        // 主线程不要立刻结束，否则CompletableFuture默认使用的线程池会立刻关闭:
        Thread.sleep(200);
    }

    static String queryCode(String name, String url) {
        System.out.println("query code from " + url + "...");
        try {
            Thread.sleep((long) (Math.random() * 100));
        } catch (InterruptedException e) {
        }
        return "601857";
    }

    static Double fetchPrice(String code, String url) {
        System.out.println("query price from " + url + "...");
        try {
            Thread.sleep((long) (Math.random() * 100));
        } catch (InterruptedException e) {
        }
        return 5 + Math.random() * 20;
    }


}
